package org.saxonextensions.eml.dispatcher.servlet;

import org.saxonextensions.eml.emitter.MailSessionFactory;
import org.saxonextensions.eml.dispatcher.AbstractFileEMLDispatcher;

import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.util.Properties;

/**
 * Servlet Context Listener EML Dispatcher.
 *
 * @author Ivan Latysh <ivan@yourmail.com>
 * @version 0.1
 * @since 4-Mar-2009 1:51:48 PM
 */
public class ServletContextListenerEMLDispatcher implements ServletContextListener {

  /** eml directory init parameter name */
  private static final String EML_DIRECTORY = "eml-directory";
  /** number of milliseconds to sleep before directory scans */
  private static final String SLEEP_TIME = "sleep-time-ms";

  /** Dispather */
  private final DispatcherRunner dispatcher = new DispatcherRunner();
  /** Dispatcher thread */
  private final Thread dispatcherThread = new Thread(dispatcher);

  public void contextInitialized(ServletContextEvent servletContextEvent) {
    // get eml directory to monitor
    String _directory = servletContextEvent.getServletContext().getInitParameter(EML_DIRECTORY);
    // if eml directory is undefined, fire an exception
    if (null==_directory) throw new RuntimeException("Unable to initialize EMLDispatcher. `" + EML_DIRECTORY + "` parameter is undefined.");
    // set monitoring directory
    dispatcher.setEmlDirectory(new File(servletContextEvent.getServletContext().getRealPath(_directory)));

    // get sleep time
    String _sleepTime = servletContextEvent.getServletContext().getInitParameter(SLEEP_TIME);
    if (null!=_sleepTime) dispatcher.setSleepTime(Long.valueOf(_sleepTime));

    // try to load mail.properties
    InputStream mailPropsIn = this.getClass().getClassLoader().getResourceAsStream("mail.properties");
    if (null!=mailPropsIn) {
      try {
        Properties mailProperties = new Properties();
        mailProperties.load(mailPropsIn);
        dispatcher.setMailProperties(mailProperties);
      } catch (IOException e) {
        throw new RuntimeException("Unable to load mail properties.", e);
      }
    }

    // set thread as daemon, so we can exit even when thread is alive
    dispatcherThread.setDaemon(true);
    // start the thread
    dispatcherThread.start();
  }

  public void contextDestroyed(ServletContextEvent servletContextEvent) {
    // destroy dispatcher
    dispatcher.destroy();
    // stop the thread
    try {
      dispatcherThread.join(1000);
    } catch (InterruptedException e) {
      servletContextEvent.getServletContext().log("Interrupted while waiting for dispatcher thread to die.", e);
    }
  }

  /** EML Dispatcher runner */
  class DispatcherRunner extends AbstractFileEMLDispatcher implements Runnable {

    /** Monitored directory */
    private File emlDirectory;
    /** Sleep time */
    private long sleepTime = 5000;
    /** Interrupted flag */
    private boolean interrupted = false;

    public File getEmlDirectory() {
      return emlDirectory;
    }

    public void setEmlDirectory(File emlDirectory) {
      this.emlDirectory = emlDirectory;
    }

    public long getSleepTime() {
      return sleepTime;
    }

    public void setSleepTime(long sleepTime) {
      this.sleepTime = sleepTime;
    }

    public void setMailProperties(Properties properties) {
      MailSessionFactory.getInstance().setProps(properties);
    }

    public void run() {
      try {
        while (!interrupted) {
          dispatchAll(emlDirectory);
          synchronized (this) {
            try {
              wait(sleepTime);
            } catch (InterruptedException e) {
              interrupted = true;
            }
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

}
